package io.loli.kaze.server;
import io.loli.kaze.cache.CacheFilter;
import io.netty.handler.codec.http.HttpRequest;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Queue;
import javax.net.ssl.SSLEngine;
import org.littleshoot.proxy.ChainedProxy;
import org.littleshoot.proxy.ChainedProxyAdapter;
import org.littleshoot.proxy.ChainedProxyManager;
import org.littleshoot.proxy.HttpProxyServerBootstrap;
import org.littleshoot.proxy.SslEngineSource;
import org.littleshoot.proxy.TransportProtocol;
import org.littleshoot.proxy.impl.DefaultHttpProxyServer;
public class KazeProxy {
private String jkspw;
private String serverIp;
private Integer serverPort;
private Integer port;
private CacheFilter filter;
private Boolean cache;
private String mode;
protected ChainedProxyManager chainedProxyManager() {
return new ChainedProxyManager() {
@Override
public void lookupChainedProxies(HttpRequest httpRequest,
Queue<ChainedProxy> chainedProxies) {
chainedProxies.add(newChainedProxy());
}
};
}
protected ChainedProxy newChainedProxy() {
return new ChainedProxyAdapter() {
@Override
public TransportProtocol getTransportProtocol() {
return TransportProtocol.TCP;
}
@Override
public boolean requiresEncryption() {
return true;
}
@Override
public SSLEngine newSslEngine() {
SslEngineSource sslEngineSource = new KazeSslEngineSource(
"kclient.jks", "tclient.jks", false, true, "serverkey",
jkspw);
return sslEngineSource.newSslEngine();
}
@Override
public InetSocketAddress getChainedProxyAddress() {
try {
return new InetSocketAddress(
InetAddress.getByName(serverIp), serverPort);
} catch (UnknownHostException uhe) {
throw new RuntimeException("Unable to resolve " + serverIp);
}
}
};
}
public KazeProxy port(int port) {
this.port = port;
return this;
}
public KazeProxy serverIp(String serverIp) {
this.serverIp = serverIp;
return this;
}
public KazeProxy serverPort(Integer serverPort) {
this.serverPort = serverPort;
return this;
}
public KazeProxy password(String password) {
this.jkspw = password;
return this;
}
public KazeProxy cache(Boolean cache) {
this.cache = cache;
return this;
}
public KazeProxy filter(CacheFilter filter) {
this.filter = filter;
return this;
}
public KazeProxy mode(String mode) {
this.mode = mode;
return this;
}
public void start() throws IOException {
HttpProxyServerBootstrap boot = null;
if ("client".equals(mode)) {
boot = DefaultHttpProxyServer.bootstrap()
.withAddress(new InetSocketAddress("localhost", port))
.withChainProxyManager(chainedProxyManager())
.withTransportProtocol(TransportProtocol.TCP);
if (cache) {
boot = boot.withFiltersSource(filter);
}
} else if ("server".equals(mode)) {
SslEngineSource sslEngineSource = new KazeSslEngineSource(
"kserver.jks", "tserver.jks", false, true, "serverkey",
jkspw);
boot = DefaultHttpProxyServer.bootstrap()
.withAddress(new InetSocketAddress("0.0.0.0", port))
.withTransportProtocol(TransportProtocol.TCP)
.withSslEngineSource(sslEngineSource)
.withAuthenticateSslClients(false);
}
boot.start();
System.in.read();
}
public KazeProxy withFilter(CacheFilter cacheFilter) {
this.filter = cacheFilter;
return this;
}
}